#pragma once
#include <infiniband/verbs.h>
#include "MemoryManager.h"

/* rdma control path */

#define CQ_MAX_DEPTH 4096
#define QP_MAX_DEPTH 4096
#define WR_MAX_SGE 1
#define MAX_INLINE_SIZE 256
#define DEFAULT_GID_INDEX 2
#define DEFAULT_MEMORY_SIZE 1 << 30


#define ENABLE_SRQ 0x1
#define ENABLE_PREALLOCATE 0x1 << 1

class Rdma
{
private:
    /* data */
    static struct ibv_context *dev_ctx_;
    static struct ibv_pd *pd_;
    
    struct ibv_device_attr dev_attr_;
    uint8_t resolve_port_id_;
    struct ibv_port_attr port_attr_;
    
    struct ibv_cq *send_cq_;
    struct ibv_cq *recv_cq_;
    struct ibv_srq *srq_ = NULL;
    MemoryManager &mm_;
public:
    Rdma(MemoryManager &mm);
    ~Rdma();
    void Destroy();
    int Init(const char* dev_name, uint8_t port_id, uint8_t flag);
    struct ibv_qp* RdmaCreateQueuepair();
    int RdmaDestroyQueuepair(struct ibv_qp* qp);
    int ModifyStateERR(struct ibv_qp* qp);
    int ModifyStateINIT(struct ibv_qp* qp);
    int ModifyStateRTR(struct ibv_qp* qp, uint32_t qpn, uint16_t lid, uint8_t* gid);
    int ModifyStateRTS(struct ibv_qp* qp);
    void RdmaQueryQueuepair(struct ibv_qp* qp);
    
    int RdmaWrite(struct ibv_qp* qp, uint32_t rkey, uint64_t source_buffer, uint64_t dest_buffer, uint64_t buffer_size, uint64_t ctx);
    int RdmaSend(struct ibv_qp* qp, uint64_t buffer, uint64_t buffer_size, uint64_t ctx);
    int RdmaRead(struct ibv_qp* qp, uint32_t rkey, uint64_t source_buffer, uint64_t dest_buffer, uint64_t buffer_size, uint64_t ctx, bool signal);
    inline uint8_t get_port_id() const { return resolve_port_id_; }
    inline uint16_t get_lid() const { return port_attr_.lid; }
    inline struct ibv_srq *get_srq() const { return srq_; }
    inline struct ibv_cq *get_send_cq() const { return send_cq_; } 
    inline struct ibv_cq *get_recv_cq() const { return recv_cq_; } 
    inline struct ibv_mr *get_mr() const {return static_cast<struct ibv_mr*>(mm_.mr());}
    inline struct ibv_context *get_device_ctx() const { return dev_ctx_; }

};


